package cn.wd.service.impl;

import cn.wd.domain.Employee;
import cn.wd.domain.User;
import cn.wd.mapper.EmployeeMapper;
import cn.wd.mapper.UserMapper;
import cn.wd.page.PageResult;
import cn.wd.qo.QueryObject;
import cn.wd.service.IUserService;
import cn.wd.utils.TokenManager;
import cn.wd.vo.LoginInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    private final UserMapper mapper;
    private final EmployeeMapper employeeMapper;
    public UserServiceImpl(UserMapper mapper, EmployeeMapper employeeMapper) {
        this.mapper = mapper;
        this.employeeMapper = employeeMapper;
    }

    @Override
    public User selectUsername(String username) {
        return mapper.selectByUsername(username);
    }

    @Override
    public String login(String username, String password){
        // 1. 基于用户名去数据库查询用户信息
        User user = mapper.selectByUsername(username);

        // 2. 如果信息不存在, 提示用户名或密码错误
        if (user == null) {
            log.error("[用户服务] 登录失败, 用户名输入错误, 提交的用户名={}, 提交的密码={}", username, password);
            throw new RuntimeException("用户名或密码错误");
        }

        // 3. 判断密码是否正确, 如果不正确, 提示用户名或密码错误
        if (!password.equals(user.getPassword())) {
            log.error("[用户服务] 登录失败, 密码输入错误, 提交的用户名={}, 提交的密码={}", username, password);
            throw new RuntimeException("用户名或密码错误");
        }

        // 3.1 判断当前用户状态, 如果状态为禁用(1), 提示该用户处理禁用状态,请申请用户恢复
        if(user.getStatus() == 1){
            log.error("[用户服务] 登录失败, 该用户处于禁用状态, 提交的用户名={}, 提交的密码={}", username, password);
            throw new RuntimeException("该用户处于禁用状态");
        }

        log.info("[用户服务] 用户{}成功登录", username);

        // 4. 生成 token, 并将当前用户存入 map
        String token = TokenManager.getToken();

        LoginInfo loginInfo = new LoginInfo();
        // 将 user 中所有与 loginInfo 对象中属性名相同的属性值全部 copy 到 loginInfo
        BeanUtils.copyProperties(user, loginInfo);

        TokenManager.put(token, loginInfo);

        LoginInfo info = TokenManager.get(token);

        // 5. 返回 token
        return token;
    }


    @Override
    public void save(User obj) {
        mapper.insert(obj);
    }

    @Override
    public void deleteById(Long id) {
        mapper.deleteByPrimaryKey(id);
    }

    @Override
    public void updateById(User obj) {
        mapper.updateByPrimaryKey(obj);
    }

    @Override
    public User selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }
    @Override
    public List<User> selectAll() {
        return mapper.selectAll();
    }

    @Override
    public PageResult<User> query(QueryObject qo) {
        Long total = mapper.selectForCount(qo);
        if (total == 0) {
            return PageResult.empty(qo.getCurrentPage(), qo.getPageSize());
        }
        List<User> userList = mapper.selectForList(qo);
        return new PageResult<>(qo.getCurrentPage(), qo.getPageSize(), total, userList);
    }

    @Override
    public void changeStatus(Long id, Integer status) {
        mapper.changeStatus(id, status);
    }

    @Override
    public void logicDeleteById(Long id, boolean deleted) {
        mapper.logicDeleteById(id, deleted);
    }

    /**
     * 重置密码
     * @param token 用户的token，获取用户信息
     * @param newPassword 用户提交的新密码
     * @param oldPassword 用户提交的原始密码
     */
    @Override
    public void restPassword(String token, String newPassword, String oldPassword) {
        LoginInfo loginInfo = TokenManager.get(token);
        Employee employee = employeeMapper.selectByEmployeeName(loginInfo.getUsername());
        if (employee == null) {
            log.error("[用户重置密码业务]： token 中获取不到用户信息");
            throw new RuntimeException("用户名或密码错误！");
        }
        if (! oldPassword.equals(employee.getPassword())) {
            log.error("[用户重置密码业务]： 用户提交的密码和原始密码不符");
            throw new RuntimeException("原始密码错误，请重新再试！");
        }
        employeeMapper.restPassword(loginInfo.getId(), newPassword);
        BeanUtils.copyProperties(employee, loginInfo);
        TokenManager.put(token, loginInfo);
    }

    /**
     * 根据 token 获取用户信息
     * @param token
     * @return
     */
    @Override
    public LoginInfo getLoginInfo(String token) {
        return TokenManager.get(token);
    }
}
